import * as THREE from 'three';
// 引入性能监视器
import Stats from 'three/addons/libs/stats.module.js'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 将原生dom转换成3D物体
// 1,引入css3d渲染器
// 只关注dom并使用css的transform进行2d变换,可以和webGl的canvas搭配使用
// 2D和3D的区别,以及如何进行鼠标交互
// CSS3D物体: 不始终面向摄像机,不会被遮挡,会跟这缩放,原生dom点击
// CSS2D物体: 始终面项摄像机,不会被遮挡,不会跟着缩放,原生dom点击
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
let renderer, controls,stats,mesh,spotLightHelper,cssRenderer,scene,camera

// 初始化
function init() {
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
    renderer = new THREE.WebGLRenderer();
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );
    renderer.shadowMap.enabled = true
     // 轨道控制器
    controls = new OrbitControls( camera, renderer.domElement );
    camera.position.set(0,5,10) // 设置摄像机的位置
    // 2,初始化2D渲染器标签
    // css2D渲染器就是设置好了css2d样式的div标签
    cssRenderer = new CSS2DRenderer()
    cssRenderer.setSize(window.innerWidth, window.innerHeight)
    document.body.appendChild(cssRenderer.domElement)
    // 问题:现在由于div和canvas并列了,不能显示css3d标签
    // 解决: 所以需要把div并列到canvas的上一层(透明)
    cssRenderer.domElement.style.position = 'fixed'
    cssRenderer.domElement.style.top = 0
    cssRenderer.domElement.style.left = 0
    // 问题: div标签挡住了canvas,轨道控制器是监听ca
    // 解决方案1:把div的pointerEvent 设置为none, 不触发鼠标的交互事件(推荐)
    cssRenderer.domElement.style.pointerEvents = 'none'
    // 解决方案2: 将轨道控制器的监听事件改为css的监听事件
   /*  // 轨道控制器
    controls = new OrbitControls( camera, cssRenderer.domElement );
    camera.position.set(0,5,10) // 设置摄像机的位置 */
}

// 加入性能监视器
function createStats() {
    stats = new Stats()
    stats.setMode(0) // 0 每秒刷新帧数 1,每帧用时, 2,内存占用
    stats.domElement.style.position = 'fixed'
    stats.domElement.style.left = '0'
    stats.domElement.style.top = '0'
    document.body.appendChild(stats.domElement)

}

// 设置总体的坐标轴
function createAxes (){ // 总体的
    const axesHelper = new THREE.AxesHelper(20)
    scene.add(axesHelper)
}

// 创建聚光灯
function createLight() {
    // 聚光灯: 参数1:光源颜色,参数2: 光源强度,参数3: 光源最远发射距离,参数4:聚光灯发射角度(建议小于二分之Π,90度)
    // 参数5: 光斑周围的序号程度(0-1), 默认0 参数6: 光照衰减梁随着巨鹿越远,在这个值的基础上就越弱
    const spotLight = new THREE.SpotLight(0xffffff, 10,100,Math.PI / 6, 0.5, 1)
    spotLight.position.set(0,6,0)

    // 可以让图片作为光源的纹理,这里由于图片不透光,所以使用不了
    // spotLight.map = new THREE.TextureLoader().load('./assets/img/img01.jpg')
    // 让聚光灯照射球体
    spotLight.target = mesh
    scene.add(spotLight)
    // 聚光灯辅助线
    spotLightHelper = new THREE.SpotLightHelper(spotLight)
    // spotLightHelper.target = mesh
    scene.add(spotLightHelper)

}

// 创建一个球体，使用球体 + 标准的网格材质，来对灯光做出反应
function createSphere() {
    const geometery = new THREE.SphereGeometry(1,32,32)
    const material = new THREE.MeshStandardMaterial({
        color: 0xffff00
    })
    mesh = new THREE.Mesh(geometery, material)
    scene.add(mesh)

}

// 添加一个地面，来了解环境光
function createGround() {
    const geometery = new THREE.PlaneGeometry(100,100)
    // side用来据定哪一面被渲染,roughness: 粗糙度(0:光滑-1:粗糙)
    const material = new THREE.MeshStandardMaterial({color: 0xffffff,side: THREE.DoubleSide,roughness:0.5 })   
    const plane = new THREE.Mesh(geometery, material)
    plane.position.set(0,-1,0)
    scene.add(plane)
    plane.rotation.x = -Math.PI / 2

}

// Js创建原生DoM并转换成3D物体
function create2DDom() {
    const dom = document.createElement('span')
    dom.innerHTML = '2D小模型'
    dom.style.color = 'red'
    dom.style.fontSize = '20px'
    dom.addEventListener('clcik', ()=> {
        alert('点击了')
    })
    // 此dom不需要自己手动添加到body,而是依赖于转换后3D物体渲染,(会被three.js加入到div容器中)
    // 转换成three.js的 3d物体
    const dom2d = new CSS2DObject(dom)
    // 虽然没有材质和几何图片,但是可以使用three.js中position,rotation,scale
    dom2d.position.set(0, 2, 0)
    // 2D中物体并不会根据像素值转换成对应单位的数值
    // 如果要改变大小,只能改变像素值
    scene.add(dom2d)
    
}


// 设置动画效果,并让物体动起来
let speed = 0.01
function animate() {
	requestAnimationFrame( animate );
    mesh.position.x +=speed
    mesh.position.z += speed
    if(mesh.position.x >= 5 ){
        speed = -0.01
    }else if(mesh.position.x <= -5) {
        speed = 0.01
    }
   
    // 不断更新聚光灯的辅助线
    spotLightHelper.update()
    stats.update()
	controls.update()
	renderer.render( scene, camera );
    cssRenderer.render(scene,camera)
}
// 根据窗口大小自动按比例缩放
function resize () {
    window.addEventListener('resize', () => {
        renderer.setSize(window.innerWidth,window.innerHeight)
        camera.aspect = window.innerWidth/window.innerHeight
        camera.updateProjectionMatrix()
        cssRenderer.setSize(window.innerWidth, window.innerHeight)
    })
}
init()
resize()
createStats()
createAxes()
createSphere()
createLight()
create2DDom()
createGround()



animate()






